
export function times(timeDataArr: {
    description: string,
    'time(ms)': number
}[] = []): object[] {
    const timing = performance.timing
    const loadTime = timing.loadEventEnd - timing.navigationStart //过早获取时,loadEventEnd有时会是0
    if (loadTime <= 0) {
        setTimeout(times, 200)
        return
    }
    const readyStart = timing.fetchStart - timing.navigationStart
    const redirectTime = timing.redirectEnd - timing.redirectStart
    const appcacheTime = timing.domainLookupStart - timing.fetchStart
    const unloadEventTime = timing.unloadEventEnd - timing.unloadEventStart
    const lookupDomainTime = timing.domainLookupEnd - timing.domainLookupStart
    const connectTime = timing.connectEnd - timing.connectStart
    const requestTime = timing.responseEnd - timing.requestStart
    const initDomTreeTime = timing.domInteractive - timing.responseEnd
    const domReadyTime = timing.domComplete - timing.domInteractive //过早获取时,domComplete有时会是0
    const loadEventTime = timing.loadEventEnd - timing.loadEventStart

    const allTimes = [
        { description: "准备新页面时间耗时", 'time(ms)': readyStart },
        { description: "redirect 重定向耗时", 'time(ms)': redirectTime },
        { description: "Appcache 耗时", 'time(ms)': appcacheTime },
        { description: "unload 前文档耗时", 'time(ms)': unloadEventTime },
        { description: "DNS 查询耗时", 'time(ms)': lookupDomainTime },
        { description: "TCP连接耗时", 'time(ms)': connectTime },
        { description: "request请求耗时", 'time(ms)': requestTime },
        { description: "请求完毕至DOM加载", 'time(ms)': initDomTreeTime },
        { description: "解释dom树耗时", 'time(ms)': domReadyTime },
        { description: "load事件耗时", 'time(ms)': loadEventTime },
        { description: "从开始至load总耗时", 'time(ms)': loadTime },
    ]

    allTimes.push(...timeDataArr)
    console.table(allTimes)
    return allTimes
}


export declare interface ITimerClass {
    start(): number;
    end(): void;
    getDurationInMs(): number;
    decription: string;
}
export declare interface ITimerObj {
    [prop: number]: () => void;
}
export declare interface ITimer {
    createTimer(description: string): any;
    clearTimer(timerKey?: number, decription?: string): object;
    _timers: ITimerObj[];
}

const timerArr = [];

export const timer: ITimer = {
    _timers: timerArr,
    createTimer(description: string) {
        return new class Timer implements ITimerClass {
            public decription: string = description;
            private startTime: number;
            private endTime: number;

            constructor() { }

            start(): number {
                this.startTime = Date.now();
                const o = {};
                o[this.startTime] = this.end.bind(this, true);
                o[this.decription] = this.end.bind(this, true);
                timerArr.push(o);
                return this.startTime;
            }
            end() {
                this.endTime = Date.now();
                if (arguments.length > 0) {
                    return {
                        decription: this.decription,
                        'time(ms)': this.getDurationInMs()
                    }
                }
            }
            getDurationInMs(): number {
                if (!this.startTime || !this.endTime) return 0;
                return this.endTime - this.startTime;
            }
        }
    },
    clearTimer(timerKey?: number, decription?: string) {
        if (!timerArr.length && (timerKey || decription)) return;
        const endTimer = timerArr.find(item => item.hasOwnProperty(timerKey || decription))[timerKey || decription];
        const t = endTimer();
        timerArr.splice(timerArr.indexOf(t), 0);
        return t
    }
}